package com.luyuan.common.utils.weixin;

import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.luyuan.common.utils.http.HttpUtils;

/**
 * 微信小程序工具类
 * 
 * @author luyuan
 */
public class WxappUtil {
    private static final Logger log = LoggerFactory.getLogger(WxappUtil.class);

    /**
     * 微信小程序授权登录接口地址
     */
    private static final String JS_CODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";

    static {
        // 添加BouncyCastleProvider支持
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 通过微信小程序code获取用户信息
     * 
     * @param appid  微信小程序appid
     * @param secret 微信小程序密钥
     * @param code   微信登录code
     * @return 用户信息
     */
    public static JSONObject getSessionByCode(String appid, String secret, String code) {
        try {
            // 封装请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appid", appid);
            params.put("secret", secret);
            params.put("js_code", code);
            params.put("grant_type", "authorization_code");

            // 将Map参数转换为URL查询字符串
            String paramStr = params.entrySet().stream()
                    .map(entry -> entry.getKey() + "=" + entry.getValue())
                    .collect(Collectors.joining("&"));

            // 发送GET请求
            String result = HttpUtils.sendGet(JS_CODE_2_SESSION_URL, paramStr);

            // 解析返回结果
            JSONObject jsonObject = JSON.parseObject(result);

            // 判断是否请求成功
            if (jsonObject.containsKey("errcode")) {
                log.error("微信登录失败，错误码：{}，错误信息：{}", jsonObject.getString("errcode"), jsonObject.getString("errmsg"));
                return null;
            }

            return jsonObject;
        } catch (Exception e) {
            log.error("微信登录异常", e);
            return null;
        }
    }

    /**
     * 解密微信小程序用户敏感数据
     * 
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param sessionKey    微信 session_key
     * @param iv            加密算法的初始向量
     * @return 解密后的用户信息
     */
    public static JSONObject decryptUserInfo(String encryptedData, String sessionKey, String iv) {
        try {
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
            byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey);
            byte[] ivBytes = Base64.getDecoder().decode(iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(sessionKeyBytes, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivBytes));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);

            byte[] result = cipher.doFinal(encryptedBytes);
            return JSON.parseObject(new String(result, "UTF-8"));
        } catch (Exception e) {
            log.error("解密微信用户信息异常", e);
            return null;
        }
    }
}